/*
 * @Author: chenhj 
 * @Date: 2018-07-03 10:34:06 
 * @Descript: 
 *  这段是截取vue 事件机制的代码 
 *  https://github.com/vuejs/vue/blob/dev/dist/vue.js#L2447
 *  直接打开连接就好了
 *  实现的代码很简单
 * @Last Modified by: chenhj
 * @Last Modified time: 2018-07-03 11:14:22
 */


//类数组函数转换成数组
function toArray(list, start) {
    start = start || 0;
    var i = list.length - start;
    var ret = new Array(i);
    while (i--) {
        ret[i] = list[i + start];
    }
    return ret
}

//定义VueBus
function VueBus() {
    this._events = {}   //存储缓存的事件
}

//vue 分装的事件Mixin 
function eventsMixin(bus) {
    var hookRE = /^hook:/;

    //事件订阅
    bus.prototype.$on = function (event, fn) {
        var this$1 = this;
        var vm = this;
        //支持
        //this.$on(['subscribeName1','subscribeName2'],function(){
            
        //})
        if (Array.isArray(event)) {
            for (var i = 0, l = event.length; i < l; i++) {
                this$1.$on(event[i], fn);
            }

        //传入事件函数
        } else {
            (vm._events[event] || (vm._events[event] = [])).push(fn);
            // optimize hook:event cost by using a boolean flag marked at registration
            // instead of a hash lookup
            if (hookRE.test(event)) {
                vm._hasHookEvent = true;
            }
        }
        return vm
    };
    //只订阅一次事件
    bus.prototype.$once = function (event, fn) {
        var vm = this;

        function on() {
            vm.$off(event, on);
            fn.apply(vm, arguments);
        }
        on.fn = fn;
        vm.$on(event, on);
        return vm
    };
    //解除事件订阅
    bus.prototype.$off = function (event, fn) {
        var this$1 = this;

        var vm = this;
        // all
        if (!arguments.length) {
            vm._events = Object.create(null);
            return vm
        }
        // array of events
        if (Array.isArray(event)) {
            for (var i = 0, l = event.length; i < l; i++) {
                this$1.$off(event[i], fn);
            }
            return vm
        }
        // specific event
        var cbs = vm._events[event];
        if (!cbs) {
            return vm
        }
        if (!fn) {
            vm._events[event] = null;
            return vm
        }
        if (fn) {
            // specific handler
            var cb;
            var i$1 = cbs.length;
            while (i$1--) {
                cb = cbs[i$1];
                if (cb === fn || cb.fn === fn) {
                    cbs.splice(i$1, 1);
                    break
                }
            }
        }
        return vm
    };
    //发布事件
    bus.prototype.$emit = function (event) {
        var vm = this; {
            var lowerCaseEvent = event.toLowerCase();
            if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
                tip(
                    "Event \"" + lowerCaseEvent + "\" is emitted in component " +
                    (formatComponentName(vm)) + " but the handler is registered for \"" + event + "\". " +
                    "Note that HTML attributes are case-insensitive and you cannot use " +
                    "v-on to listen to camelCase events when using in-DOM templates. " +
                    "You should probably use \"" + (hyphenate(event)) + "\" instead of \"" + event + "\"."
                );
            }
        }
        var cbs = vm._events[event];
        if (cbs) {
            cbs = cbs.length > 1 ? toArray(cbs) : cbs;
            var args = toArray(arguments, 1);
            for (var i = 0, l = cbs.length; i < l; i++) {
                try {
                    cbs[i].apply(vm, args);
                } catch (e) {
                    console.log('handleError:',e, vm, ("event handler for \"" + event + "\""))
                    // handleError(e, vm, ("event handler for \"" + event + "\""));
                }
            }
        }
        return vm
    };
}
eventsMixin(VueBus)
export default new VueBus;